package com.nowcoder.community.controller;

        import com.nowcoder.community.contant.Entity;
        import com.nowcoder.community.annotation.LoginRequired;
        import com.nowcoder.community.entity.Comment;
        import com.nowcoder.community.entity.DiscussPost;
        import com.nowcoder.community.entity.Page;
        import com.nowcoder.community.entity.User;
        import com.nowcoder.community.property.QiniuProperty;
        import com.nowcoder.community.service.*;
        import com.nowcoder.community.utils.CommunityUtils;
        import com.nowcoder.community.utils.HostHolder;
        import com.qiniu.util.Auth;
        import com.qiniu.util.StringMap;
        import lombok.extern.slf4j.Slf4j;
        import org.apache.commons.lang3.StringUtils;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.beans.factory.annotation.Value;
        import org.springframework.http.HttpStatus;
        import org.springframework.security.core.annotation.AuthenticationPrincipal;
        import org.springframework.stereotype.Controller;
        import org.springframework.ui.Model;
        import org.springframework.web.bind.annotation.*;
        import org.springframework.web.multipart.MultipartFile;

        import javax.servlet.ServletOutputStream;
        import javax.servlet.http.HttpServletResponse;
        import java.io.*;
        import java.util.*;

@Controller
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Value("${community.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Value("${community.path.header}")
    private String headerDir;

    @Autowired
    private QiniuProperty qiniuProperty;

    @Autowired
    private UserService userService;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private LikeService likeService;

    @Autowired
    private FollowService followService;

    @Autowired
    private DisccusPostService disccusPostService;

    @Autowired
    private CommentService commentService;

    /*
     * 获取 账号设置页面
     * */
    @LoginRequired
    @GetMapping("/setting")
    public String getSettingPage(Model model){
        // 将头像上传到七牛云
        String filename = CommunityUtils.generateUUID(); // 1. 避免同名文件被覆盖；2.避免云缓存

        // 设置响应
        Map<String, Object> map = new HashMap<>();
        String headerUrl = qiniuProperty.getHeader().getBucketUrl() + "/" + filename;
        map.put("headerUrl", headerUrl);
        StringMap policy = new StringMap();
        policy.put("returnBody", CommunityUtils.getJsonString(200, null, map));
        // 根据文件名生成 token
        Auth auth = Auth.create(qiniuProperty.getKey().getAccessKey(), qiniuProperty.getKey().getSecretKey());
        String uploadToken = auth.uploadToken(qiniuProperty.getHeader().getBucketName(), filename, 60, policy);

        model.addAttribute("uploadToken", uploadToken);
        model.addAttribute("filename", filename);
        model.addAttribute("uploadUrl", qiniuProperty.getUploadUrl());
        return "/site/setting";
    }


    @PostMapping("/updateHeaderUrl")
    @ResponseBody
    public String updateHeaderUrl(String headerUrl, @AuthenticationPrincipal User user){
        if (StringUtils.isBlank(headerUrl))
            return CommunityUtils.getJsonString(400, "非法头像路径");

        userService.updateHeader(user.getId(), headerUrl);
        return CommunityUtils.getJsonString(200);
    }


    /**
     * 废弃
     * 处理头像上传
     *
     * Deprecated 重构：将头像上传到七牛云
     * */
    @Deprecated
    @LoginRequired
    @PostMapping("/upload")
    // 如果是上传多个文件，可以将 MultipartFile 声明为数组
    public String uploadHeader(MultipartFile headerImage, Model model){
        if (headerImage == null){
            model.addAttribute("uploadMsg", "图片不能为空");
            return "/site/setting";
        }
        String[] contentType = headerImage.getContentType().split("/");
        if (!contentType[0].equals("image")){
            model.addAttribute("uploadMsg", "文件格式不允许");
            return "/site/setting";
        }

        // 生产唯一的文件名并将图片保存到硬盘
        String filename = CommunityUtils.generateUUID() + "." + contentType[1];
        File dest = new File(headerDir + "/" + filename);
        String headerUrl = domain + contextPath + "/user/header/" + filename;
        try {
            headerImage.transferTo(dest); // 保存到硬盘
            userService.updateHeader(hostHolder.getUser().getId(), headerUrl);
        } catch (IOException e) {
            log.error("头像图片写入硬盘失败：" + e.getMessage());
            throw new RuntimeException("上传头像失败", e);
        }
        return "redirect:/index";
    }

    /**
     * 废弃
     * 获取 头像图片
     *
     * Deprecated: 重构 - 将头像上传到七牛云
     * */
    @Deprecated
    @GetMapping("/header/{filename}")
    public void getHeaderImage(@PathVariable String filename, HttpServletResponse response){
        filename = headerDir + "/" + filename;
        response.setContentType("image/" + filename.substring(filename.lastIndexOf(".")));
        try (
                FileInputStream fileInputStream = new FileInputStream(filename);
                ServletOutputStream outputStream = response.getOutputStream()
        ){
            int b = 0;
            byte[] buffer = new byte[1024];
            while ((b = fileInputStream.read(buffer)) != -1){
                outputStream.write(buffer);
            }
        } catch (IOException e) {
            log.error("从硬盘读取头像图片失败");
        }
    }

    /*
    * 修改密码
    * */
    @LoginRequired
    @PostMapping("/update_password")
    public String updatePassword(String password, String newPassword, @CookieValue("ticket") String ticket, Model model){
        User user = hostHolder.getUser();
        if (user == null)
            throw new RuntimeException("用户未登录");

        if (StringUtils.isBlank(password) || StringUtils.isBlank(newPassword)){
            model.addAttribute("passwordMsg", "密码不能为空");
            return "/site/setting";
        }

        if (!user.getPassword().equals(CommunityUtils.md5(password, user.getSalt()))){
            model.addAttribute("passwordMsg", "密码不正确");
            return "/site/setting";
        }

        if (user.getPassword().equals(CommunityUtils.md5(newPassword, user.getSalt()))){
            model.addAttribute("newPasswordMsg", "新密码不能和旧密码相同");
            return "/site/setting";
        }
        userService.updatePassword(user.getEmail(), newPassword);
        userService.logoutUser(ticket);
        return "redirect:/login";
    }

    @GetMapping("/profile/{userId}")
    public String getProfilePage(
            @PathVariable("userId") int userId,
            Model model,
            HttpServletResponse response) throws IOException {

        User loginUser = hostHolder.getUser();
        User user = userService.findUserById(userId);
        if (user == null)
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "找不到该用户");

        model.addAttribute("user", user);
        model.addAttribute("likeCount", likeService.countUserLikes(userId));
        model.addAttribute("hasFollowed", loginUser == null ? false : followService.hasFollowed(loginUser.getId(), Entity.USER, userId));
        model.addAttribute("followingCount", followService.countFollowing(userId, Entity.USER));
        model.addAttribute("followerCount", followService.countFollower(Entity.USER, userId));
        return "/site/profile";
    }


    // 粉丝列表
    @GetMapping("/follower/{userId}")
    public String getUserFollowerPage(@PathVariable("userId") int userId, Page page, Model model){
        User user = userService.findUserById(userId);
        if (user == null)
            throw new RuntimeException("用户不存在");

        page.setLimit(5);
        page.setPath("/user/follower/" + userId);
        page.setRows(followService.countFollower(Entity.USER, userId));

        List<Map<String, Object>> followers = followService.findFollowers(userId, page.getOffset(), page.getLimit());
        model.addAttribute("users", addHasFollowedToList(followers));
        model.addAttribute("user", user);
        return "/site/follower";
    }

    // 关注列表
    @GetMapping("/following/{userId}")
    public String getFollowingPage(@PathVariable("userId") int userId, Page page, Model model){
        User user = userService.findUserById(userId);
        if (user == null)
            throw new RuntimeException("用户不存在");

        page.setLimit(5);
        page.setPath("/user/following/" + userId);
        page.setRows(followService.countFollowing(userId, Entity.USER));
        List<Map<String, Object>> followings = followService.findFollowings(userId, page.getOffset(), page.getLimit());
        model.addAttribute("users", addHasFollowedToList(followings));
        model.addAttribute("user", user);
        return "/site/followee";
    }

    @GetMapping("/posts/{userId}")
    public String getMyPostPage(@PathVariable("userId") int userId, Page page, Model model){
        User user = userService.findUserById(userId);
        if (user == null)
            throw new RuntimeException("用户不存在");

        int postCount = disccusPostService.findDiscussPostRows(userId);
        page.setLimit(5);
        page.setPath("/user/posts/" + userId);
        page.setRows(postCount);
        List<DiscussPost> posts = disccusPostService.findDiscussPost(userId, page.getOffset(), page.getLimit());
        List<Map<String, Object>> list = new LinkedList<>();
        for (DiscussPost post: posts){
            Map<String, Object> map = new HashMap<>();
            map.put("post", post);
            map.put("likeCount", likeService.countEntityLikes(Entity.DISCUSS_POST, post.getId()));
            list.add(map);
        }
        model.addAttribute("postCount", postCount);
        model.addAttribute("posts", list);
        model.addAttribute("user", user);
        return "/site/my-post";
    }

    @GetMapping("/reply/{userId}")
    public String getMyReplyPage(@PathVariable("userId") int userId, Page page, Model model){
        User user = userService.findUserById(userId);
        if (user == null)
            throw new RuntimeException("用户不存在");

        int commentCount = commentService.countCommentsByUserId(userId, Entity.DISCUSS_POST);
        page.setLimit(5);
        page.setPath("/user/reply/" + userId);
        page.setRows(commentCount);
        List<Comment> comments = commentService.findCommentsByUserId(userId, Entity.DISCUSS_POST, page.getOffset(), page.getLimit());
        List<Map<String, Object>> list = new LinkedList<>();
        for (Comment comment: comments){
            Map<String, Object> map = new HashMap<>();
            map.put("post", disccusPostService.findDiscussPostById(comment.getEntityId()));
            map.put("comment", comment);
            list.add(map);
        }
        model.addAttribute("user", user);
        model.addAttribute("posts", list);
        model.addAttribute("commentCount", commentCount);
        return "/site/my-reply";
    }

    private List<Map<String, Object>> addHasFollowedToList(List<Map<String, Object>> list){
        for (Map<String, Object> entity: list){
            User u = (User) entity.get("user");
            entity.put("hasFollowed",  hostHolder.getUser() == null ? false : followService.hasFollowed(hostHolder.getUser().getId(), Entity.USER, u.getId()));
        }
        return list;
    }
}
